package com.wiscamp.ninechapters.common.core;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

public class RandomHelper {
    private RandomHelper() {
    }

    /**
     * 随机指定范围内N个不重复的数
     * 在初始化的无重复待选数组中随机产生一个数放入结果中，
     * 将待选数组被随机到的数，用待选数组(len-1)下标对应的数替换
     * 然后从len-2里随机产生下一个随机数，如此类推
     *
     * @param maxValue 指定范围最大值
     * @param minValue 指定范围最小值
     * @param quantity 随机数个数
     * @return int[] 随机数结果集
     */
    public static int[] randomArray(int minValue, int maxValue, int quantity) {
        int len = maxValue - minValue + 1;
        if (maxValue < minValue || quantity > len) {
            return new int[]{};
        }

        //初始化给定范围的待选数组
        int[] source = new int[len];
        for (int i = minValue; i < minValue + len; i++) {
            source[i - minValue] = i;
        }

        int[] result = new int[quantity];
        var random = new SecureRandom();
        int index = 0;
        for (int i = 0; i < result.length; i++) {
            //待选数组0到(len-2)随机一个下标
            index = Math.abs(random.nextInt() % len--);
            //将随机到的数放入结果集
            result[i] = source[index];
            //将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
            source[index] = source[len];
        }
        return result;
    }

    /**
     * 从列表中随机获取若干数量的子列表
     *
     * @param numbers
     * @param quantity
     * @return
     */
    public static Collection<Long> getRandomCollection(Collection<Long> numbers, int quantity) {
        if (quantity >= numbers.size()) return numbers;
        Collection<Long> resultIds = new ArrayList<>();
        int[] indexes = RandomHelper.randomArray(1, numbers.size() - 1, quantity);
        Object[] itemArray = numbers.toArray();
        for (int i = 0; i <= Objects.requireNonNull(indexes).length - 1; i++) {
            int tempIndex = indexes[i];
            resultIds.add((Long) itemArray[tempIndex]);
        }
        return resultIds;
    }

    /**
     * 获取随机Integer数字
     *
     * @param bound
     * @return
     */
    public static Integer getRandomInteger(int bound) {
        var random = new SecureRandom();
        return random.nextInt(bound);
    }

    /**
     * 获取随机Long数字
     *
     * @return
     */
    public static Long getRandomLong() {
        var random = new SecureRandom();
        return random.nextLong();
    }
}
